package com.xbongbong.workflow.service.strategy.data.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.TaskTypeEnum;
import com.xbongbong.paas.pojo.dto.SaasFormSaveDTO;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.wrap.UserVO;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.paas.util.FormDataUtil;
import com.xbongbong.pro.constant.BusinessConstant;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.formdata.pojo.SaasNeedRedundantAttrPojo;
import com.xbongbong.pro.workflow.enums.WorkflowOperateEnum;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.PurchaseProductEntity;
import com.xbongbong.saas.domain.entity.ReturnedPurchaseProductEntity;
import com.xbongbong.saas.domain.entity.ext.InstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.PurchaseEntityExt;
import com.xbongbong.saas.domain.entity.ext.ReturnedPurchaseEntityExt;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.product.ReturnPurchaseProductEnum;
import com.xbongbong.saas.help.ReturnPurchaseHelp;
import com.xbongbong.saas.model.InstockModel;
import com.xbongbong.saas.model.InstockProductModel;
import com.xbongbong.saas.model.PaasFormSubDataModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseProductModel;
import com.xbongbong.saas.model.ReturnedPurchaseModel;
import com.xbongbong.saas.model.ReturnedPurchaseProductModel;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.workflow.domain.entity.WorkflowBackupDataEntity;
import com.xbongbong.workflow.model.WorkflowBackupDataModel;
import com.xbongbong.workflow.pojo.Data;
import com.xbongbong.workflow.pojo.User;
import com.xbongbong.workflow.pojo.WorkflowTransferPOJO;
import com.xbongbong.workflow.service.strategy.data.AbstractWorkflowDataStrategy;
import com.xbongbong.workflow.service.strategy.data.WorkflowDataProcessStrategy;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleFromFormData;
import static com.xbongbong.saas.toolbox.help.FastJsonHelper.getDoubleOrDefaultFromFormData;

/**
 *
 * @author 魏荣杰
 *
 */
@Service
public class WorkflowReturnPurchaseStrategy extends AbstractWorkflowDataStrategy implements WorkflowDataProcessStrategy {


    private static Logger log = LoggerFactory.getLogger(WorkflowReturnPurchaseStrategy.class);


    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private PurchaseProductModel purchaseProductModel;
    @Resource
    private InstockProductModel instockProductModel;
    @Resource
    private InstockModel instockModel;
    @Resource
    private ReturnedPurchaseModel returnedPurchaseModel;
    @Resource
    private ReturnPurchaseHelp returnPurchaseHelp;
    @Resource
    private WorkflowBackupDataModel workflowBackupDataModel;
    @Resource
    private ReturnedPurchaseProductModel returnedPurchaseProductModel;
    @Resource
    private PaasFormSubDataModel paasFormSubDataModel;


    @Override
    public List<Integer> type() {
        return Collections.singletonList(XbbRefTypeEnum.RETURNED_PURCHASE.getCode());
    }

    @Override
    public void save(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {
        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long returnedPurchaseId = pojoData.getId();
        User user = workflowTransferPOJO.getUser();
        String creatorId = user.getUserId();
        JSONArray product = data.getJSONArray(ReturnedPurchaseEnum.PRODUCTS.getAttr());
        Map<Long, JSONObject> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.nonNull(product)) {
            for (int i = 0; i < product.size(); i++) {
                JSONObject json = product.getJSONObject(i);
                if (Objects.nonNull(json.getLong(BusinessConstant.PRODUCT_SUB_ID))) {
                    productMap.put(json.getLong(BusinessConstant.PRODUCT_SUB_ID), json);
                }
            }
        }
        ReturnedPurchaseEntityExt returnedPurchaseEntityExt = returnedPurchaseModel.getByKey(returnedPurchaseId, corpid);

        Long purchaseSheetId = FastJsonHelper.getLongFromFormData(data, ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr());

        Boolean productCanSee = saasNeedRedundantAttrPojo.getAttrCanSee(ReturnedPurchaseEnum.PRODUCTS.getAttr());
        // 有出库单但是没有出库完毕
        //更新采购合同关联退货单id
        PurchaseEntityExt purchase = purchaseModel.getByKey(purchaseSheetId, corpid);
        JSONObject dataList = purchase.getData();
        dataList.put(PurchaseEnum.RETURNED_PURCHASE_ID.getAttr(),purchaseSheetId);
        if (productCanSee) {

            Map<Long, Double> changeNumMap = new HashMap<>();
            // 序列号处理
            List<ReturnedPurchaseProductEntity> returnedPurchaseProductEntities = returnedPurchaseProductModel.getProductsByRetPurchaseId(corpid, returnedPurchaseId);
            if (CollectionsUtil.isNotEmpty(returnedPurchaseProductEntities)) {
                for (ReturnedPurchaseProductEntity returnedPurchaseProductEntity : returnedPurchaseProductEntities) {
                    JSONObject productEntityData = returnedPurchaseProductEntity.getData();
                    if (Objects.nonNull(productEntityData.getLong(BusinessConstant.REF_PRODUCT_ID))) {
                        changeNumMap.put(productEntityData.getLong(BusinessConstant.REF_PRODUCT_ID), Arith.sub(returnedPurchaseProductEntity.getProductNum(), 0D));
                    }

                    returnPurchaseHelp.saveSerial(returnedPurchaseProductEntity, returnedPurchaseId, corpid, data, productMap);
                }
            }



            JSONArray jsonArray = data.getJSONArray(ReturnedPurchaseEnum.PRODUCTS.getAttr());
            List<Long> refList = new ArrayList<>();
            Map<Long, Double> refNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Double> returnProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Double> allOldReturnNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Set<Long> noDelList = new HashSet<>();
            if (Objects.nonNull(jsonArray)) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
                    Long refProductId = FastJsonHelper.getLongFromFormData(jsonObject, BusinessConstant.REF_PRODUCT_ID);
                    if (Objects.nonNull(refProductId)) {
                        refList.add(refProductId);
                        noDelList.add(refProductId);
                        refNumMap.put(refProductId, changeNumMap.getOrDefault(refProductId, getDoubleFromFormData(jsonObject, ReturnPurchaseProductEnum.NUM.getAttr())));
                        Double num = returnProductNumMap.getOrDefault(pageProductId, 0D);
                        num = Arith.add(num, changeNumMap.getOrDefault(pageProductId, getDoubleFromFormData(jsonObject, ReturnPurchaseProductEnum.NUM.getAttr())));
                        returnProductNumMap.put(pageProductId, num);
                    }else {
                        Double num = allOldReturnNumMap.getOrDefault(pageProductId, 0D);
                        num += changeNumMap.getOrDefault(pageProductId, getDoubleFromFormData(jsonObject, ReturnPurchaseProductEnum.NUM.getAttr()));
                        allOldReturnNumMap.put(pageProductId, num);
                    }
                }
            }
            for (Map.Entry<Long, Double> entry : changeNumMap.entrySet()) {
                if (!noDelList.contains(entry.getKey())) {
                    refList.add(entry.getKey());
                    refNumMap.put(entry.getKey(), entry.getValue());
                    returnProductNumMap.put(entry.getKey(), entry.getValue());
                }
            }
            if (!refList.isEmpty()) {
                List<PurchaseProductEntity> purchaseProductEntities = purchaseProductModel.getProductsByPurchaseId(corpid, purchaseSheetId);
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("corpid", corpid);
                params.put("idIn", refList);
                params.put("del", DelEnum.NORMAL.getDel());
                List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(params);
//                老数据
                HashSet<Long> oldInstockIds = new HashSet<>();
                Map<Long, Double> refNumsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                instockProductEntityList.forEach(item -> {
                    if (Objects.nonNull(item.getRefProductId()) && refNumMap.containsKey(item.getId())) {
                        item.setOutstockNum(Arith.add(item.getOutstockNum() == null ? 0D : item.getOutstockNum(), refNumMap.get(item.getId())));
                        refNumsMap.put(item.getRefProductId(), Arith.add(refNumMap.get(item.getId()),refNumsMap.getOrDefault(item.getRefProductId(), 0D)));
                    }else {
                        oldInstockIds.add(item.getIntoWarehouseId());
                    }
                });
                instockProductModel.updateBatch(instockProductEntityList, corpid);
                if (!refNumsMap.isEmpty()){
                    dataList.put(PurchaseEnum.RETURNED_PURCHASE_ID.getAttr(), BasicConstant.ONE);
                    for (PurchaseProductEntity item : purchaseProductEntities) {
                        Double outstockNum = item.getOutstockNum() == null ? 0D : item.getOutstockNum();
                        if (refNumsMap.containsKey(item.getId())) {
                            item.setOutstockNum(Arith.add(outstockNum, refNumsMap.getOrDefault(item.getId(), 0D)));
                        }
                        if (Arith.sub(item.getInstockNum(), item.getOutstockNum()) > 0) {
                            dataList.put(PurchaseEnum.RETURNED_PURCHASE_ID.getAttr(), BasicConstant.ZERO);
                        }
                    }
                    purchaseProductModel.updateBatch(purchaseProductEntities, corpid);
                }
                if (!oldInstockIds.isEmpty()) {
                    params.clear();
                    params.put("corpid", corpid);
                    params.put("idIn", oldInstockIds);
                    params.put("del", DelEnum.NORMAL.getDel());
                    HashSet<Long> purchaseIds = new HashSet<>();
                    List<InstockEntityExt> entitys = instockModel.findEntitys(params);
                    entitys.forEach(item -> {
                        Long purchaseId = item.getData().getLong(InstockEnum.REF_ID.getAttr());
                        purchaseIds.add(purchaseId);
                    });
                    if (!purchaseIds.isEmpty()) {
                        params.clear();
                        params.put("corpid", corpid);
                        params.put("purchaseIdIn", purchaseIds);
                        params.put("del", DelEnum.NORMAL.getDel());
                        List<PurchaseProductEntity> entitys1 = purchaseProductModel.findEntitys(params);

                        for (PurchaseProductEntity entity : entitys1) {
                            if (returnProductNumMap.containsKey(entity.getProductId())) {
                                // 剩余未退
                                Double unStockNum = Arith.sub(entity.getProductNum(), entity.getOutstockNum());
                                Double amendNum = returnProductNumMap.get(entity.getProductId());
                                Double outstocknNum;
                                Double inNum = Arith.sub(amendNum, unStockNum);
                                if (inNum > 0) {
                                    outstocknNum = entity.getProductNum();
                                    returnProductNumMap.put(entity.getProductId(), inNum);
                                }else {
                                    outstocknNum = Arith.add(entity.getOutstockNum(), amendNum);
                                    returnProductNumMap.remove(entity.getProductId());
                                }
                                entity.setOutstockNum(outstocknNum);
                                entity.setUpdateTime(DateTimeUtil.getInt());
                            }
                        }
                        purchaseProductModel.updateBatch(entitys1, corpid);
                    }

                }

            }

            if (!allOldReturnNumMap.isEmpty()) {
                // 采购退货没有refproductid的情况

                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("corpid", corpid);
                params.put("purchaseSheetId", purchaseSheetId);
                params.put("del", DelEnum.NORMAL.getDel());
                List<PurchaseProductEntity> entitys = purchaseProductModel.findEntitys(params);
                entitys.forEach(item ->{
                    if (allOldReturnNumMap.containsKey(item.getProductId())) {
                        // 剩余未退
                        Double unStockNum = Arith.sub(item.getProductNum(), item.getOutstockNum());
                        Double amendNum = allOldReturnNumMap.get(item.getProductId());
                        Double outstockNum;
                        Double outNum = Arith.sub(amendNum, unStockNum);
                        if (outNum > 0) {
                            outstockNum = item.getProductNum();
                            allOldReturnNumMap.put(item.getProductId(), outNum);
                        }else {
                            outstockNum = Arith.add(item.getOutstockNum(), amendNum);
                            allOldReturnNumMap.remove(item.getProductId());
                        }
                        item.setOutstockNum(outstockNum);
                        item.setUpdateTime(DateTimeUtil.getInt());
                    }
                });
                purchaseProductModel.updateBatch(entitys, corpid);
            }

        }
        purchaseModel.save(purchase);

//        ReRollBackEntity reRollBackEntity = associatedBusinessAfterSavePojo.getReRollBackEntity();

        SaasFormSaveDTO saasFormSaveDTO = new SaasFormSaveDTO();
        saasFormSaveDTO.setCorpid(corpid);
        UserVO userVO = new UserVO();
        BeanUtil.copyProperties(creatorId, userVO);
        saasFormSaveDTO.setLoginUser(userVO);
        saasFormSaveDTO.setUserId(creatorId);
        saasFormSaveDTO.setLoginUserName(user.getName());
        saasFormSaveDTO.setNewPaasFormDataEntity(returnedPurchaseEntityExt);
        saasFormSaveDTO.setNewData(data);
        saasFormSaveDTO.setOldData(data);
        saasFormSaveDTO.setOldPaasFormDataEntity(returnedPurchaseEntityExt);

        //关联红冲付款单新建
        List<Long> redPaySheetIds = returnPurchaseHelp.generateRedPay(data.getJSONArray(ReturnedPurchaseEnum.PAY_SHEETS.getAttr()) , saasFormSaveDTO);
//        reRollBackEntity.setRedSheetId(redPaySheetIds);
        // --关联发票红冲/作废--*/
        List<Long> invoiceIds = returnPurchaseHelp.saveReturnedPurchaseInvoice(saasFormSaveDTO, data.getJSONArray(ReturnedPurchaseEnum.INVOICES.getAttr()));
//        reRollBackEntity.setRedInvoiceId(invoiceIds);
        // 更新采购退货中关联发票和关联红冲付款单字段内容（红冲发票和红冲付款单属于新建，其id在新建成功后才能拿到）
        JSONObject updateData = new JSONObject();
        if (!invoiceIds.isEmpty()) {
            updateData.put(ReturnedPurchaseEnum.INVOICES.getAttr(), invoiceIds);
        } else {
            updateData.put(ReturnedPurchaseEnum.INVOICES.getAttr(), null);
            updateData.put(ReturnedPurchaseEnum.INVOICES_LINKED_TEXT.getAttr(), null);
        }
        if (!redPaySheetIds.isEmpty()) {
            updateData.put(ReturnedPurchaseEnum.PAY_SHEETS.getAttr(), redPaySheetIds);
//            if (associatedBusinessAfterSavePojo.getRefundAmount() != null) {
//                returnedPurchaseData.put(ReturnedPurchaseEnum.RETURNED_PURCHASE_AMOUNT.getAttr(), associatedBusinessAfterSavePojo.getRefundAmount());
//            }
            Double refundAmount = getDoubleOrDefaultFromFormData(data, ReturnedPurchaseEnum.RETURNED_PURCHASE_AMOUNT.getAttr(), 0D);
            if (refundAmount != null) {
                updateData.put(ReturnedPurchaseEnum.RETURNED_PURCHASE_AMOUNT.getAttr(), refundAmount);
            }
        } else {
            updateData.put(ReturnedPurchaseEnum.PAY_SHEETS.getAttr(), null);
            updateData.put(ReturnedPurchaseEnum.PAY_SHEETS_LINKED_TEXT.getAttr(), null);
        }
//        JSONArray productArray = SaveFormatHelp.formatSelectProduct4Save2(data, ReturnedPurchaseEnum.PRODUCTS.getAttr());
//        updateData.put(ReturnedPurchaseEnum.PRODUCTS.getAttr(), data.get(ReturnedPurchaseEnum.PRODUCTS.getAttr()));
        List<UpdateDataEntity> list = new ArrayList<>();
        list.add(ExplainUtil.getUpdateData(returnedPurchaseId, updateData, corpid));
        returnedPurchaseModel.updateBatch(list, corpid);
//        newReturnedPurchaseEntityExt.getData().put(ReturnedPurchaseEnum.PRODUCTS.getAttr(), productArray);

        // api
        apiHook(workflowTransferPOJO);
        addLinkDataDynamic(workflowTransferPOJO);
        // log
        afterSaveLog(workflowTransferPOJO);
    }

    @Override
    public void update(WorkflowTransferPOJO workflowTransferPOJO, SaasNeedRedundantAttrPojo saasNeedRedundantAttrPojo) throws XbbException {

        // 文件柜
        saveDataCabinetFile(workflowTransferPOJO);

        String corpid = workflowTransferPOJO.getCorpid();
        Data pojoData = workflowTransferPOJO.getData();
        JSONObject data = pojoData.getData();
        Long dataId = pojoData.getId();


        Long purchaseSheetId = FastJsonHelper.getLongFromFormData(data, ReturnedPurchaseEnum.PURCHASE_SHEET_ID.getAttr());

        Boolean productCanSee = saasNeedRedundantAttrPojo.getAttrCanSee(ReturnedPurchaseEnum.PRODUCTS.getAttr());
        JSONArray product = data.getJSONArray(ReturnedPurchaseEnum.PRODUCTS.getAttr());
        Map<Long, JSONObject> productMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        if (Objects.nonNull(product)) {
            for (int i = 0; i < product.size(); i++) {
                JSONObject json = product.getJSONObject(i);
                if (Objects.nonNull(json.getLong(BusinessConstant.PRODUCT_SUB_ID))) {
                    productMap.put(json.getLong(BusinessConstant.PRODUCT_SUB_ID), json);
                }
            }
        }
        // 有出库单但是没有出库完毕
        Boolean hasOut = !Objects.equals(FastJsonHelper.getLongOrDefaultFromFormData(data, ReturnedPurchaseEnum.OUTSTOCK_ID.getAttr(),0L), 0L);
        //更新采购合同关联退货单id
        PurchaseEntityExt purchase = purchaseModel.getByKey(purchaseSheetId, corpid);
        JSONObject dataList = purchase.getData();
        dataList.put(PurchaseEnum.RETURNED_PURCHASE_ID.getAttr(),purchaseSheetId);
        if (productCanSee) {
            // 更新退货产品
//            Map<Long, Double> changeNumMap = returnPurchaseHelp.setReturnedPurchaseProducts(returnedPurchaseEntityExt);
            Map<Long, Double> changeNumMap = new HashMap<>();

            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(workflowTransferPOJO.getBackupDataId(), corpid);
            JSONObject oldData = workflowBackupDataEntity.getData();
            List<ReturnedPurchaseProductEntity> oldReturnedPurchaseProducts = JSON.parseArray(oldData.getString(StringConstant.PRODUCT), ReturnedPurchaseProductEntity.class);

            Map<Long, ReturnedPurchaseProductEntity> oldProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            oldReturnedPurchaseProducts.forEach(v -> oldProductMap.put(v.getId(), v));

            List<ReturnedPurchaseProductEntity> returnedPurchaseProductEntities = returnedPurchaseProductModel.getProductsByRetPurchaseId(corpid, dataId);
            // 序列号处理
            for (ReturnedPurchaseProductEntity returnedPurchaseProductEntity : returnedPurchaseProductEntities) {
                JSONObject jsonObject = returnedPurchaseProductEntity.getData();
                Long productId = returnedPurchaseProductEntity.getId();
                if (Objects.nonNull(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID))) {
                    returnedPurchaseProductEntity.setRefProductId(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID));
                    changeNumMap.put(jsonObject.getLong(BusinessConstant.REF_PRODUCT_ID), Arith.sub(returnedPurchaseProductEntity.getProductNum(), oldProductMap.get(productId).getProductNum() == null ? 0D : oldProductMap.get(productId).getProductNum()));
                }
                if (oldProductMap.containsKey(productId)) {
                    oldProductMap.remove(productId);
                } else {
                    // 新增
                    returnPurchaseHelp.saveSerial(returnedPurchaseProductEntity, dataId, corpid, data, productMap);
                }
            }

            for (Map.Entry<Long, ReturnedPurchaseProductEntity> entry : oldProductMap.entrySet()) {
                ReturnedPurchaseProductEntity value = entry.getValue();
                changeNumMap.put(value.getRefProductId(), Arith.sub(0D, value.getProductNum()));
                // 删除产品时，更新序列号结存记录，删除序列号流水记录
                returnPurchaseHelp.updateSerial(value);
            }


            JSONArray jsonArray = data.getJSONArray(ReturnedPurchaseEnum.PRODUCTS.getAttr());
            List<Long> refList = new ArrayList<>();
            Map<Long, Double> refNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Double> returnProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Double> allOldReturnNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Set<Long> noDelList = new HashSet<>();
            if (Objects.nonNull(jsonArray)) {
                for (int i = 0; i < jsonArray.size(); i++) {
                    JSONObject jsonObject = jsonArray.getJSONObject(i);
                    Long pageProductId = jsonObject.getLong(SelectProductEnum.PRODUCT.getAttr());
                    Long refProductId = FastJsonHelper.getLongFromFormData(jsonObject, BusinessConstant.REF_PRODUCT_ID);
                    if (Objects.nonNull(refProductId)) {
                        refList.add(refProductId);
                        noDelList.add(refProductId);
                        refNumMap.put(refProductId, changeNumMap.getOrDefault(refProductId, getDoubleFromFormData(jsonObject, ReturnPurchaseProductEnum.NUM.getAttr())));
                        Double num = returnProductNumMap.getOrDefault(pageProductId, 0D);
                        num = Arith.add(num, changeNumMap.getOrDefault(pageProductId, getDoubleFromFormData(jsonObject, ReturnPurchaseProductEnum.NUM.getAttr())));
                        returnProductNumMap.put(pageProductId, num);
                    }else {
                        Double num = allOldReturnNumMap.getOrDefault(pageProductId, 0D);
                        num += changeNumMap.getOrDefault(pageProductId, getDoubleFromFormData(jsonObject, ReturnPurchaseProductEnum.NUM.getAttr()));
                        allOldReturnNumMap.put(pageProductId, num);
                    }
                }
            }
            for (Map.Entry<Long, Double> entry : changeNumMap.entrySet()) {
                if (!noDelList.contains(entry.getKey())) {
                    refList.add(entry.getKey());
                    refNumMap.put(entry.getKey(), entry.getValue());
                    returnProductNumMap.put(entry.getKey(), entry.getValue());
                }
            }
            if (!refList.isEmpty()) {
                List<PurchaseProductEntity> purchaseProductEntities = purchaseProductModel.getProductsByPurchaseId(corpid, purchaseSheetId);
                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("corpid", corpid);
                params.put("idIn", refList);
                params.put("del", DelEnum.NORMAL.getDel());
                List<InstockProductEntity> instockProductEntityList = instockProductModel.findEntitys(params);
//                老数据
                HashSet<Long> oldInstockIds = new HashSet<>();
                Map<Long, Double> refNumsMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                instockProductEntityList.forEach(item -> {
                    if (Objects.nonNull(item.getRefProductId()) && refNumMap.containsKey(item.getId())) {
                        item.setOutstockNum(Arith.add(item.getOutstockNum() == null ? 0D : item.getOutstockNum(), refNumMap.get(item.getId())));
                        refNumsMap.put(item.getRefProductId(), Arith.add(refNumMap.get(item.getId()),refNumsMap.getOrDefault(item.getRefProductId(), 0D)));
                    }else {
                        oldInstockIds.add(item.getIntoWarehouseId());
                    }
                });
                instockProductModel.updateBatch(instockProductEntityList, corpid);
                if (!refNumsMap.isEmpty()){
                    dataList.put(PurchaseEnum.RETURNED_PURCHASE_ID.getAttr(), BasicConstant.ONE);
                    for (PurchaseProductEntity item : purchaseProductEntities) {
                        Double outstockNum = item.getOutstockNum() == null ? 0D : item.getOutstockNum();
                        if (refNumsMap.containsKey(item.getId())) {
                            item.setOutstockNum(Arith.add(outstockNum, refNumsMap.getOrDefault(item.getId(), 0D)));
                        }
                        if (Arith.sub(item.getInstockNum(), item.getOutstockNum()) > 0) {
                            dataList.put(PurchaseEnum.RETURNED_PURCHASE_ID.getAttr(), BasicConstant.ZERO);
                        }
                    }
                    purchaseProductModel.updateBatch(purchaseProductEntities, corpid);
                }
                if (!oldInstockIds.isEmpty()) {
                    params.clear();
                    params.put("corpid", corpid);
                    params.put("idIn", oldInstockIds);
                    params.put("del", DelEnum.NORMAL.getDel());
                    HashSet<Long> purchaseIds = new HashSet<>();
                    List<InstockEntityExt> entitys = instockModel.findEntitys(params);
                    entitys.forEach(item -> {
                        Long purchaseId = item.getData().getLong(InstockEnum.REF_ID.getAttr());
                        purchaseIds.add(purchaseId);
                    });
                    if (!purchaseIds.isEmpty()) {
                        params.clear();
                        params.put("corpid", corpid);
                        params.put("purchaseIdIn", purchaseIds);
                        params.put("del", DelEnum.NORMAL.getDel());
                        List<PurchaseProductEntity> entitys1 = purchaseProductModel.findEntitys(params);

                        for (PurchaseProductEntity entity : entitys1) {
                            if (returnProductNumMap.containsKey(entity.getProductId())) {
                                // 剩余未退
                                Double unStockNum = Arith.sub(entity.getProductNum(), entity.getOutstockNum());
                                Double amendNum = returnProductNumMap.get(entity.getProductId());
                                Double outstocknNum;
                                Double inNum = Arith.sub(amendNum, unStockNum);
                                if (inNum > 0) {
                                    outstocknNum = entity.getProductNum();
                                    returnProductNumMap.put(entity.getProductId(), inNum);
                                }else {
                                    outstocknNum = Arith.add(entity.getOutstockNum(), amendNum);
                                    returnProductNumMap.remove(entity.getProductId());
                                }
                                entity.setOutstockNum(outstocknNum);
                                entity.setUpdateTime(DateTimeUtil.getInt());
                            }
                        }
                        purchaseProductModel.updateBatch(entitys1, corpid);
                    }

                }

            }

            if (!allOldReturnNumMap.isEmpty()) {
                // 采购退货没有refproductid的情况

                Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                params.put("corpid", corpid);
                params.put("purchaseSheetId", purchaseSheetId);
                params.put("del", DelEnum.NORMAL.getDel());
                List<PurchaseProductEntity> entitys = purchaseProductModel.findEntitys(params);
                entitys.forEach(item ->{
                    if (allOldReturnNumMap.containsKey(item.getProductId())) {
                        // 剩余未退
                        Double unStockNum = Arith.sub(item.getProductNum(), item.getOutstockNum());
                        Double amendNum = allOldReturnNumMap.get(item.getProductId());
                        Double outstockNum;
                        Double outNum = Arith.sub(amendNum, unStockNum);
                        if (outNum > 0) {
                            outstockNum = item.getProductNum();
                            allOldReturnNumMap.put(item.getProductId(), outNum);
                        }else {
                            outstockNum = Arith.add(item.getOutstockNum(), amendNum);
                            allOldReturnNumMap.remove(item.getProductId());
                        }
                        item.setOutstockNum(outstockNum);
                        item.setUpdateTime(DateTimeUtil.getInt());
                    }
                });
                purchaseProductModel.updateBatch(entitys, corpid);
            }

        }
        purchaseModel.save(purchase);


        // api
        apiHook(workflowTransferPOJO);
        // log
        afterUpdateLog(workflowTransferPOJO);

    }

    @Override
    public void updateBack(Long taskId, WorkflowTransferPOJO workflowTransferPOJO) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Long backupDataId = workflowTransferPOJO.getBackupDataId();
            Long dataId = workflowTransferPOJO.getData().getId();
            WorkflowBackupDataEntity workflowBackupDataEntity = workflowBackupDataModel.getByKey(backupDataId, corpid);
            if (Objects.nonNull(workflowBackupDataEntity)) {
                JSONObject data = workflowBackupDataEntity.getData();

                replenishAttrForBackupData(workflowTransferPOJO.getData().getData(), data);

                ReturnedPurchaseEntityExt returnedPurchaseEntityExt = new ReturnedPurchaseEntityExt();
                returnedPurchaseEntityExt.setId(dataId);
                returnedPurchaseEntityExt.setCorpid(corpid);
                returnedPurchaseEntityExt.setData(data);
                returnedPurchaseEntityExt.setSerialNo(data.getString(FieldTypeEnum.SERIALNO.getAlias()));
                returnedPurchaseEntityExt.setOwnerId(getOwnerId(data));
                returnedPurchaseEntityExt.setDepartmentId(data.getLong(FieldTypeEnum.DEPARTMENTID.getAlias()));

                List<ReturnedPurchaseProductEntity> list = JSON.parseArray(data.getString(StringConstant.PRODUCT), ReturnedPurchaseProductEntity.class);

                FormDataUtil.removeSystemData(data);
                data.remove(StringConstant.PRODUCT);
                if (Objects.equals(workflowTransferPOJO.getOperate(), WorkflowOperateEnum.UPDATE.getType())) {
                    returnedPurchaseEntityExt.setFlowStatus(FlowStatusEnum.PASS.getType());
                }
                returnedPurchaseModel.update(returnedPurchaseEntityExt);
                // 退货产品 在编辑中，无法更改，无需还原
                // 回退被删掉的子表单
                updateBackSubForm(returnedPurchaseEntityExt, corpid, IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE_SUB);
                //回退被删掉的富文本
                updateBackRichText(taskId, workflowTransferPOJO);

                saveProduct(list, corpid, returnedPurchaseEntityExt.getId());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowReturnPurchaseStrategy.updateBack error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    @Override
    public void approvalFailed(Long taskId, WorkflowTransferPOJO workflowTransferPOJO, Integer taskType) throws XbbException {
        try {
            String corpid = workflowTransferPOJO.getCorpid();
            Data workflowData = workflowTransferPOJO.getData();
            Long dataId = workflowData.getId();
            Long formId = workflowData.getFormId();
            Integer businessType = workflowData.getBusinessType();
            Integer saasMark = workflowData.getSaasMark();
            ReturnedPurchaseEntityExt returnedPurchaseEntityExt = new ReturnedPurchaseEntityExt();
            returnedPurchaseEntityExt.setId(dataId);
            if (Objects.equals(TaskTypeEnum.REVOKE.getType(), taskType)) {
                returnedPurchaseEntityExt.setFlowStatus(FlowStatusEnum.REVOKE.getType());
            } else {
                returnedPurchaseEntityExt.setFlowStatus(FlowStatusEnum.REJECT.getType());
            }
            returnedPurchaseEntityExt.setCorpid(corpid);
            returnedPurchaseEntityExt.setUpdateTime(DateTimeUtil.getInt());
            returnedPurchaseModel.update(returnedPurchaseEntityExt);
            // 子表单
            DelEnum del = DelEnum.APPROVE_FAILED;

            paasFormSubDataModel.deleteBatchByDataId(Collections.singletonList(dataId), corpid, IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE_SUB, del);
            //富文本
            deleteFormRichText(dataId, corpid, formId, businessType, saasMark, DelEnum.NORMAL);

            List<ReturnedPurchaseProductEntity> productList = returnedPurchaseProductModel.getProductsByRetPurchaseId(corpid, dataId);
            if (CollectionUtils.isNotEmpty(productList)) {
                List<Long> idIn = new ArrayList<>();
                productList.forEach(item->idIn.add(item.getId()));
                returnedPurchaseProductModel.deleteBatch(idIn, corpid, DelEnum.APPROVE_FAILED.getDel());
            }
        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowReturnPurchaseStrategy.approvalFailed error", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }

    private void saveProduct(List<ReturnedPurchaseProductEntity> list, String corpid, Long dataId) throws XbbException {
        try {
            List<ReturnedPurchaseProductEntity> productList = returnedPurchaseProductModel.getProductsByRetPurchaseId(corpid, dataId);
            List<Long> deleteIdIn = new ArrayList<>();

            // 遍历备份表中的产品
            List<Long> backupProductId = new ArrayList<>();
            list.forEach(item->backupProductId.add(item.getId()));


            // 移除掉备份表中的产品
            productList.forEach(item->{
                if (!backupProductId.contains(item.getId())) {
                    deleteIdIn.add(item.getId());
                }
            });

            if (CollectionsUtil.isNotEmpty(deleteIdIn)) {
                returnedPurchaseProductModel.deleteBatch(deleteIdIn, corpid, DelEnum.DELETE.getDel());
            }
            if (CollectionsUtil.isNotEmpty(list)) {
                returnedPurchaseProductModel.updateMulti(list, corpid);
            }


        } catch (Exception e) {
            log.error("com.xbongbong.workflow.service.strategy.data.impl.WorkflowPurchaseStrategy.saveProduct error ", e);
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
        }
    }
}
